☰ See All Chapters |
Spring @Configuration Annotation
When a class is annotated with @Configuration annotation, spring container process that class and generates the beans from all the methods those annotated with @Bean annotation.
package com.java4coding;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration;
@Configuration public class SpringConfiguration {
@Bean(name="mangoBean") public Mango getMangoBean() { return new Mango(); }
@Bean(name="appleBean") public Apple getAppleBean() { return new Apple(); } } |
We can have multiple classes annotated with @Configuration annotation.
package com.java4coding;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration;
@Configuration public class MangoConfiguration { @Bean(name="mangoBean") public Mango getMangoBean() { return new Mango(); } } |
package com.java4coding;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration;
@Configuration public class AppleConfiguration { @Bean(name="appleBean") public Apple getAppleBean() { return new Apple(); } } |
How to bootstrap configuration class
Classes annotated with @Configuration can be bootstrapped using either AnnotationConfigApplicationContext or AnnotationConfigWebApplicationContext. We have the below three ways to register the configuration class with AnnotationConfigApplicationContext or AnnotationConfigWebApplicationContext.
By Calling register method of AnnotationConfigApplicationContext
By passing Class objects of all configuration classes to constructor of AnnotationConfigApplicationContext
By passing package name to constructor of AnnotationConfigApplicationContext
By Calling register method of AnnotationConfigApplicationContext
Create a new AnnotationConfigApplicationContext and then call register(java.lang.Class...) method to register the configuration classes. register method accepts multiple configuration classes Class objects and bootstrap them, register method has below signature.
public void register(java.lang.Class<?>... annotatedClasses)
package com.java4coding;
import org.springframework.context.ConfigurableApplicationContext; import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class Demo { public static void main(String[] args) { AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(); context.register(MangoConfiguration.class, AppleConfiguration.class); context.refresh(); Apple apple = (Apple) context.getBean("appleBean"); Mango mango = (Mango) context.getBean("mangoBean"); mango.printFruitName(); apple.printFruitName(); ((ConfigurableApplicationContext)context).close(); } } |
It is very important to call refresh() method after all configuration classes’ registration. Otherwise we will get IllegalStateException error when we try to get any bean from the context.
By passing Class objects of all configuration classes to constructor of AnnotationConfigApplicationContext
Create a new AnnotationConfigApplicationContext by passing Class objects of all configuration classes to its constructor
package com.java4coding;
import org.springframework.context.ConfigurableApplicationContext; import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class Demo { public static void main(String[] args) { AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MangoConfiguration.class, AppleConfiguration.class); Apple apple = (Apple) context.getBean("appleBean"); Mango mango = (Mango) context.getBean("mangoBean"); mango.printFruitName(); apple.printFruitName(); ((ConfigurableApplicationContext) context).close(); } } |
In this case it is not necessary to call refresh() method and spring bootstraps the configuration classes by automatically refreshing the context.
By passing package name to constructor of AnnotationConfigApplicationContext
Create a new AnnotationConfigApplicationContext by passing package name. In this case we can pass the each package name separately or we can pass single base package of all other packages.
AnnotationConfigApplicationContext context
= new AnnotationConfigApplicationContext(
"com.java4coding.apple", "com.java4coding.mango" );
OR
AnnotationConfigApplicationContext context
= new AnnotationConfigApplicationContext(
"com.java4coding" );
In both the case it is not necessary to call refresh() method and spring bootstraps the configuration classes by automatically refreshing the context.
package com.java4coding;
import org.springframework.context.ConfigurableApplicationContext; import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class Demo { public static void main(String[] args) { //AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext("com.java4coding.apple", "com.java4coding.mango" ); AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext("com.java4coding" ); Apple apple = (Apple) context.getBean("appleBean"); Mango mango = (Mango) context.getBean("mangoBean"); mango.printFruitName(); apple.printFruitName(); ((ConfigurableApplicationContext) context).close(); } } |
Spring @Configuration Annotation Example
pom.xml
<project xmlns="https://maven.apache.org/POM/4.0.0" xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="https://maven.apache.org/POM/4.0.0 https://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.java4coding</groupId> <artifactId>Spring3_Configuration_Example</artifactId> <packaging>jar</packaging> <version>1.0-SNAPSHOT</version> <name>Spring3_Configuration_Example</name> <url>https://maven.apache.org</url> <properties> <org.springframework.version>3.2.0.RELEASE</org.springframework.version> </properties> <dependencies> <dependency> <groupId>cglib</groupId> <artifactId>cglib</artifactId> <version>2.2.2</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-core</artifactId> <version>${org.springframework.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-beans</artifactId> <version>${org.springframework.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>${org.springframework.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context-support</artifactId> <version>${org.springframework.version}</version> </dependency> </dependencies> </project> |
Apple.java
package com.java4coding;
public class Apple{ public void printFruitName(){ System.out.println("Apple"); } } |
Mango.java
package com.java4coding;
public class Mango { public void printFruitName(){ System.out.println("Mango"); } } |
SpringConfiguration.java
package com.java4coding;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration;
import com.java4coding.Mango;
@Configuration public class SpringConfiguration { @Bean(name = "mangoBean") public Mango getMangoBean() { return new Mango(); }
@Bean(name = "appleBean") public Apple getAppleBean() { return new Apple(); } } |
Demo.java
package com.java4coding;
import org.springframework.context.ConfigurableApplicationContext; import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class Demo { public static void main(String[] args) { AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext("com.java4coding" ); Apple apple = (Apple) context.getBean("appleBean"); Mango mango = (Mango) context.getBean("mangoBean"); mango.printFruitName(); apple.printFruitName(); ((ConfigurableApplicationContext) context).close(); } } |
Output:
Mango Apple |
What if class is not annotated with @Configuration annotation
@Bean annotation can be used methods whose class is not annotated with @Configuration. For example, bean methods may be declared in a @Component class or even in a plain old class. In such cases, a @Bean method will get processed in a so-called 'lite' mode. In lite mode, spring will not create any proxy for such classes; Spring does not intercept the invocation via a CGLIB proxy. This is analogous to inter-@Transactional method calls where in proxy mode, Spring does not intercept the invocation - Spring does so only in AspectJ mode.
Hence in lite mode bean methods will be treated as plain factory methods by the container (similar to factory-method declarations in XML), with scoping and lifecycle callbacks properly applied.
'inter-bean references' are not supported in lite mode. Instead, when one @Bean-method invokes another @Bean-method in lite mode, the invocation is a standard Java method invocation; For the below configuration class we have removed @Configuration by commenting, In this case getAppleConsumerBean() method will get a new instance of Apple bean. Hence we will have two instances of Apple bean.
package com.java4coding;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration;
import com.java4coding.AppleConsumer;
//@Configuration public class SpringConfiguration { @Bean(name = "appleConsumerBean") public AppleConsumer getAppleConsumerBean() { return new AppleConsumer(getAppleBean()); }
@Bean(name = "appleBean") public Apple getAppleBean() { return new Apple(); } } |
The below two images show you the two execution by annotating with @Configuration annotation and without using @Configuration annotation.
All Chapters